package com.codeoss.framework.webide.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.data.metadata.Column;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.db.util.ValueNamePairUtil;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.report.def.DetailReport;
import com.codeoss.framework.report.def.Field;
import com.codeoss.framework.report.def.FieldConditionStyle;
import com.codeoss.framework.report.util.DetailReportModel;
import com.codeoss.framework.report.util.DetailReportUtil;
import com.codeoss.framework.util.StringUtils;
import com.codeoss.framework.util.ValueNamePair;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.webide.request.DetailReportDesignerRequest;
import com.codeoss.framework.webide.response.DetailReportDesignerResponse;
import com.codeoss.framework.webide.service.IDetailReportDesignerService;
import com.codeoss.module.ir.model.IrReport;
import com.codeoss.module.ir.service.IIrReportService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class DetailReportDesignerService implements IDetailReportDesignerService {
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private IIrReportService irReportService;
	@Autowired
	private DetailReportUtil detailReportUtil;
	@Autowired
	private ValueNamePairUtil valueNamePairUtil;
	@Override
	public DetailReportDesignerResponse initDataSourceConfigPage(String code) {
		// TODO Auto-generated method stub
		DetailReportDesignerResponse detailReportDesignerResponse = new DetailReportDesignerResponse();
		YunContext yunContext=YunContext.getCurrentContext();
		Table modelTable=tableStore.get("ir_model");
		List<ValueNamePair> tableList = valueNamePairUtil.getValueNamePairList(yunContext, modelTable, null, false, true);
		detailReportDesignerResponse.setTableList(tableList);

		QueryWrapper<IrReport> query=new QueryWrapper<IrReport>();
		query.eq("code", code);
		IrReport irReport=irReportService.getOne(query);
		String jsonContent=irReport.getJsonContent();
		if(!StringUtils.isEmpty(jsonContent)) {
			DetailReport detailReport=detailReportUtil.buildDetailReportFromIrReport(irReport);
			Map<String,Object> dataSourceConfigMap=new HashMap<String,Object>();
			detailReportDesignerResponse.setDataSourceConfig(dataSourceConfigMap);
			
			DataSourceConfig dataSourceConfig=detailReport.getDataSourceConfig();
			dataSourceConfigMap.put("id", dataSourceConfig.getId());
			dataSourceConfigMap.put("tableName", dataSourceConfig.getTableName());
			dataSourceConfigMap.put("name", dataSourceConfig.getName());
			Expression expression=dataSourceConfig.getWhereClause();
			if(expression!=null) {
				dataSourceConfigMap.put("whereClause", expression.getScript());
			}
			dataSourceConfigMap.put("orderBy", dataSourceConfig.getOrderBy());
		}
		return detailReportDesignerResponse;
	}

	@Override
	public DetailReportDesignerResponse initDisplayFieldConfigPage(String code,String tableName) {
		// TODO Auto-generated method stub
		DetailReportDesignerResponse detailReportDesignerResponse = new DetailReportDesignerResponse();
		
		QueryWrapper<IrReport> query=new QueryWrapper<IrReport>();
		query.eq("code", code);
		IrReport irReport=irReportService.getOne(query);
		String jsonContent=irReport.getJsonContent();
		List<Field> fieldList=null;
		String reportTableName=null;
		if(!StringUtils.isEmpty(jsonContent)) {
			DetailReport detailReport=detailReportUtil.buildDetailReportFromIrReport(irReport);
			fieldList=detailReport.getFieldList();
			reportTableName=detailReport.getDataSourceConfig().getTableName();
		}
		
		Table table = tableStore.get(tableName);
		List<Column> columnList = table.getAllColumnList();
		List<Map<String, Object>> fieldMapList = new ArrayList<Map<String, Object>>();
		detailReportDesignerResponse.setFieldList(fieldMapList);
		if(tableName.equals(reportTableName) && fieldList!=null && fieldList.size()>0) {
			List<String> processedColumnList=new ArrayList<String>();
			for(int i=0;i<fieldList.size();i++) {
				Field field=fieldList.get(i);
				Column column=table.getColumnByColumnName(field.getColumnName());
				if(column==null) {
					continue;
				}
				Map<String, Object> fieldMap = new HashMap<String, Object>();
				fieldMapList.add(fieldMap);
				fieldMap.put("display", true);
				fieldMap.put("columnName", column.getColumnName());
				fieldMap.put("name", column.getName());
				fieldMap.put("viewType", field.getViewType());
				processedColumnList.add(column.getColumnName());
			}
			for(int i=0;i<columnList.size();i++) {
				Column column = columnList.get(i);
				if(processedColumnList.contains(column.getColumnName())) {
					continue;
				}
				Map<String, Object> fieldMap = getFieldMap(column);
				fieldMapList.add(fieldMap);
			}
		}else {
			for (int i = 0; i < columnList.size(); i++) {
				Column column = columnList.get(i);
				Map<String, Object> fieldMap = getFieldMap(column);
				fieldMapList.add(fieldMap);
			}
		}
		return detailReportDesignerResponse;
	}

	private Map<String,Object> getFieldMap(Column column){
		Map<String, Object> fieldMap = new HashMap<String, Object>();
		fieldMap.put("display", false);
		fieldMap.put("columnName", column.getColumnName());
		fieldMap.put("name", column.getName());
		fieldMap.put("viewType", "label");
		if (column.getDataType().equals("boolean")) {
			fieldMap.put("viewType", "switch");
		} else if (column.getLookupInfo() != null && column.getLookupInfo().getDictDef() != null) {
			fieldMap.put("viewType", "tag");
		}
		return fieldMap;
	}
	
	@Override
	public DetailReportDesignerResponse initReportPreviewPage(DetailReportDesignerRequest request) {
		// TODO Auto-generated method stub
		DetailReportDesignerResponse detailReportDesignerResponse = new DetailReportDesignerResponse();
		DetailReport detailReport=detailReportUtil.buildDetailReportFromJson(request.getJson());
		DetailReportModel detailReportData=detailReportUtil.buildDetailReportData(detailReport);
		detailReportDesignerResponse.setDetailReportData(detailReportData);
		return detailReportDesignerResponse;
	}

	@Override
	@Transactional
	public DetailReportDesignerResponse onFinish(DetailReportDesignerRequest request) {
		// TODO Auto-generated method stub
		DetailReportDesignerResponse detailReportDesignerResponse = new DetailReportDesignerResponse();
		DetailReport detailReport=detailReportUtil.buildDetailReportFromJson(request.getJson());
		String reportJson=null;
		try {
			reportJson = objectMapper.writeValueAsString(detailReport);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
		QueryWrapper<IrReport> query=new QueryWrapper<IrReport>();
		query.eq("code", request.getCode());
		IrReport irReport=irReportService.getOne(query);
		irReport.setJsonContent(reportJson);
		irReportService.update(irReport);
		return detailReportDesignerResponse;
	}
	
	@Override
	public DetailReportDesignerResponse initFieldConditionStylePage(String code) {
		// TODO Auto-generated method stub
        DetailReportDesignerResponse detailReportDesignerResponse = new DetailReportDesignerResponse();
		
		QueryWrapper<IrReport> query=new QueryWrapper<IrReport>();
		query.eq("code", code);
		IrReport irReport=irReportService.getOne(query);
		String jsonContent=irReport.getJsonContent();
		DetailReport detailReport=null;
		if(!StringUtils.isEmpty(jsonContent)) {
			detailReport=detailReportUtil.buildDetailReportFromIrReport(irReport);
		}
		if(detailReport!=null) {
			List<FieldConditionStyle> fieldConditionStyleList=detailReport.getFieldConditionStyleList();
			
			List<Map<String, Object>> styleData=new ArrayList<Map<String, Object>>();
			detailReportDesignerResponse.setStyleData(styleData);
			for(FieldConditionStyle fieldConditionStyle:fieldConditionStyleList) {
				Map<String,Object> styleMap=new HashMap<String,Object>();
				styleData.add(styleMap);
				styleMap.put("field", fieldConditionStyle.getField());
				styleMap.put("condition", fieldConditionStyle.getCondition()==null?"":fieldConditionStyle.getCondition().getScript());
				styleMap.put("style", fieldConditionStyle.getStyle());
			}
		}
		return detailReportDesignerResponse;
	}

	@Override
	public DetailReportDesignerResponse previewPageDataPage(DetailReportDesignerRequest request) {
		// TODO Auto-generated method stub
		DetailReportDesignerResponse detailReportDesignerResponse = new DetailReportDesignerResponse();
		DetailReport detailReport=detailReportUtil.buildDetailReportFromJson(request.getJson());
		DetailReportModel detailReportData=detailReportUtil.buildDetailReportData(detailReport,request.getPage());
		detailReportDesignerResponse.setDetailReportData(detailReportData);
		return detailReportDesignerResponse;
	}
}
